package jsu.blogger.service.impl;
import jsu.blogger.config.RedisKeyPrefixConfig;
import jsu.blogger.controller.DraftController;
import jsu.blogger.mapper.DraftMapper;
import jsu.blogger.mapper.DraftTagMapper;
import jsu.blogger.mapper.PostMapper;
import jsu.blogger.pojo.BlogPostDetails;
import jsu.blogger.pojo.Draft;
import jsu.blogger.pojo.Post;
import jsu.blogger.pojo.Result;
import jsu.blogger.service.inter.DraftService;
import jsu.blogger.service.inter.PostService;
import jsu.blogger.util.FileUtil;
import jsu.blogger.util.RegularUtil;
import jsu.blogger.util.ReturnResultUtil;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Service
public class DraftServiceImpl implements DraftService {
    private static final Logger logger = LoggerFactory.getLogger(DraftController.class);
    @Autowired
    private DraftMapper draftMapper;
    @Autowired
    private DraftTagMapper draftTagMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

   public void  insertDraft(Draft draft){
        draftMapper.insertDraft(draft);
    }
    // 根据draftId判断记录是否存在
    public boolean exists(String draftId) {
        Draft draft = draftMapper.findById(draftId);
        return draft != null;  // 如果返回的 draft 为 null，说明记录不存在
    }
    public Draft getDraftById(String draftId) {

        return draftMapper.findById(draftId);  // 如果返回的 draft 为 null，说明记录不存在
    }

    // 删除草稿
    public boolean deleteDraft(Long userId, String draftId) {
        // 执行删除操作并判断返回的影响行数
        int rowsAffected = draftMapper.deleteDraftByUserIdAndDraftId(userId, draftId);
        boolean boo=rowsAffected > 0;
        if(boo){
            try {
                //要求删除草稿的相关文件夹和文件
                FileUtil.deleteDirectory(new File(FileUtil.createDirPath(FileUtil.TEMP_POST_IMG_DIR_NAME + File.separator + draftId)));
                logger.info("删除整个临时文件夹" + draftId);
                String dir = FileUtil.resourcePath + File.separator + FileUtil.TEMP_POST_COVER_DIR_NAME;
                FileUtil.deleteFilesByPartialName(dir, draftId);
                logger.info("删除临时文件： " + dir + ", 前缀名: " + draftId);
            }catch(Exception e){
                logger.error(draftId+"草稿相关文件删除失败");
            }
        }
        return boo;  // 如果受影响行数大于0，表示删除成功
    }
   public List<Draft> selectDraftsByUserId( Long userId, long limit, long offset){
       return draftMapper.selectDraftsByUserId(userId,limit,offset);
    }
    // 获取 draft 详情
    public Draft findAllById(String draftId) {
        return draftMapper.findAllById(draftId);
    }

    // 查询草稿的标题和内容
    public Draft getDraftTitleAndContentById(String draftId) {
        return draftMapper.getDraftTitleAndContentById(draftId);
    }
    // 根据 draftId 更新草稿
    public void updateDraft(Draft draft) {
        draftMapper.updateDraftById(draft);
    }

    // 查询草稿的其他信息（包括标签）
    public Draft getDraftOtherDetailsById(String draftId) {
        return draftMapper.getDraftOtherDetailsById(draftId);
    }
    // 检查草稿是否存在
    public boolean checkDraftExists(String draftId, Long userId, Long postId) {
        return draftMapper.checkDraftExists(draftId, userId, postId);
    }

    public void deleteDraft(String draftId) {
        draftMapper.deleteDraftById(draftId);}
    @Transactional
    public void updateDraftTags(String draftId, List<String> newTagNames) {
        try {
            logger.info("更新+"+draftId+"的标签"+newTagNames);
            // 删除草稿与标签的所有关联
            draftTagMapper.deleteByDraftId(draftId);
           // logger.info("删除");
            // 插入新的草稿标签关联
            for (String tagName : newTagNames) {
                // 根据标签名查找 tag_id
                Long tagId = draftTagMapper.findTagIdByTagName(tagName);
               // logger.info("查找"+tagId);
                if (tagId != null) {
                    // 如果找到了 tag_id，则插入关联
                    draftTagMapper.insertDraftTag(draftId, tagId);
                   // logger.info("插入");
                } else {
                    throw new RuntimeException("标签名 " + tagName + " 未找到，操作失败，事务已回滚");
                }
            }
        } catch (Exception e) {
            logger.error("更新标签出错了");
            // 如果出现异常，Spring 会自动回滚事务
            throw new RuntimeException("操作失败，事务已回滚", e);
        }
    }

    @Autowired
    private PostMapper postMapper;

    @Transactional // 确保该方法在一个事务中执行
    public Result saveDraft(Draft newDraft, Map<String, Object> requestBody) {
        try {
            String draftId = (String) requestBody.get("draftId");
            String content = (String) requestBody.get("content"); // 获取内容
           // String description=(String) requestBody.get("description");//获取相关描述
            long userId = Long.parseLong(String.valueOf(requestBody.get("userId")));
            long resourceId = Long.parseLong(String.valueOf(requestBody.get("resourceId")));
            String coverOption = (String) requestBody.get("coverOption"); // 获取有无封面
            String type = (String) requestBody.get("type");
            if("release".equals(type)){
               return releaseDraft(draftId,userId,resourceId,newDraft);
            }
            // 根据 draftId 查询草稿是否存在
            Draft draft =getDraftById(draftId);
            if (draft == null) {
                // 草稿不存在，插入新草稿
                if (resourceId <= 0 &&resourceId!=-1) {
                    return ReturnResultUtil.failure("resourceId错误");
                }
                if(resourceId!=-1) {
                    boolean postExists = postMapper.countPostsByPostIdAndPostType(resourceId, userId, 0) > 0;
                    if (!postExists) {
                        return ReturnResultUtil.failure("resourceId错误");
                    }
                    //这是想要以某篇博客为基础作修改
                    /*
                     *    <p><img src="" data-local="blob:http://localhost:8080/89efa3d4-8fd5-4386-b75e-9919329a99e7" data-custom="storageFileName=1734273739310_1_964_1.jpg"></p><p>哈哈哈哈</p>
                     *
                     * */
                    //非发布保存
                    logger.info("内容是以谁为基础 " + content);
                    List<String> storageFileNames = RegularUtil.extractStorageFileNames(content);
                    for (String fileName : storageFileNames) {
                        //正则表达式
                        List<String> parts = RegularUtil.splitFileName(fileName);
                        String frontPart = parts.get(0);  // 资源id
                        String backPart = parts.get(1);//文件名
                        String fileExtension = "";
                        if (backPart != null && backPart.lastIndexOf(".") > 0) {
                            fileExtension = backPart.substring(backPart.lastIndexOf(".") + 1).toLowerCase();
                        }
                        if (frontPart.equals(String.valueOf(resourceId))) {
                            //移动图片
                            String sourcePathStr = FileUtil.createDirPath(FileUtil.POST_IMG_DIR_NAME + File.separator + frontPart + File.separator + backPart);
                            Path sourcePath = Paths.get(sourcePathStr);  // 源文件路径
                            String targetDirStr = FileUtil.createDirPath(FileUtil.TEMP_POST_IMG_DIR_NAME + File.separator + draftId);
                            Path targetDir = Paths.get(targetDirStr);  // 目标目录路径
                            File maxFile = FileUtil.getMaxValueFileInDirectory(targetDirStr);
                            // System.out.println(file.getName());
                            String newFileName = "1";
                            if (maxFile != null) {
                                newFileName = String.valueOf(Integer.parseInt(Objects.requireNonNull(FileUtil.extractNumber(maxFile.getName()))) + 1);
                            }
                            newFileName = newFileName + "." + fileExtension;
                            boolean isCopy = FileUtil.copyFileAndRename(sourcePath, targetDir, newFileName);
                            if (isCopy) {
                                //修改content
                                newDraft.setContent(FileUtil.replaceStorageFileName(newDraft.getContent(), fileName, draftId + "_" + newFileName));
                            }
                        }
                    }


                }
                // 存在
                logger.info("插入草稿 草稿内容"+newDraft.getContent());
                if(newDraft.getPostId()==-1){
                    newDraft.setPostId(null);
                }
                if("saveTitleAndContent".equals(type)){
                    newDraft.setCoverOption("single");
                    newDraft.setArticleType("original");
                }
                // 插入新草稿数据
                insertDraft(newDraft);
            } else {
                //草稿已存在，进行更新
                if (!draft.getUserId().equals(userId)) {
                    return ReturnResultUtil.failure("userId错误");
                }
                if (draft.getPostId()!=null &&!draft.getPostId().equals(resourceId)) {
                    return ReturnResultUtil.failure("resourceId错误");
                }

                logger.info("更新草稿");
                // 更新现有草稿
                updateDraft(newDraft);
            }

            // 更新草稿标签
            if ("saveAll".equals(type)) {
                logger.info("更新草稿标签");
                // 更新草稿标签
                updateDraftTags(newDraft.getDraftId(), newDraft.getTags());
            }
            // 删除封面图片（如果有）
            if ("none".equals(coverOption)) {
                logger.info("删除封面");
                String dir = FileUtil.resourcePath + File.separator + FileUtil.TEMP_POST_COVER_DIR_NAME;
                FileUtil.deleteFilesByPartialName(dir, draftId);
            }
            // 返回成功
            logger.info("草稿保存成功"+draftId+", "+userId+", "+resourceId);

            return ReturnResultUtil.success("");
        }catch (Exception e){
            logger.error(""+e);
            return ReturnResultUtil.failure("保存失败");
            // 如果出现异常，Spring 会自动回滚事务
           // throw new RuntimeException("操作失败，事务已回滚", e);
        }
    }

    @Autowired
    private PostService postService;
    @Transactional
    public Result releaseDraft(String draftId,long userId,long resourceId,Draft newDraft){
        Long postId=null;
        try{
            Draft draft =getDraftById(draftId);
            if (draft == null) {
                // 草稿不存在，插入新草稿
                if (resourceId <= 0 && resourceId != -1) {
                    return ReturnResultUtil.failure("resourceId错误");
                }
                if(resourceId!=-1) {
                    //判断博客是否存在
                    boolean postExists = postMapper.countPostsByPostIdAndPostType(resourceId, userId, 0) > 0;
                    if (!postExists) {
                        return ReturnResultUtil.failure("resourceId错误");
                    }
                }

            }else{
                //草稿已存在 并验证成功
                if (!draft.getUserId().equals(userId)) {
                    return ReturnResultUtil.failure("userId错误");
                }
                if (draft.getPostId()!=null &&!draft.getPostId().equals(resourceId)) {
                    return ReturnResultUtil.failure("resourceId错误");
                }
                logger.info("删除一切相关草稿");
                //根据id删除草稿的一切数据
                draftTagMapper.deleteByDraftId(draftId);
                deleteDraft(draftId);
            }

            //发布草稿 插入博客 获得生成的postId
            Post post=new Post();
            post.setUserId(newDraft.getUserId());
            post.setTitle(newDraft.getTitle());
            post.setContent(newDraft.getContent());
            post.setPostType(0);
            post.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));
            post.setUpdatedAt(Timestamp.valueOf(LocalDateTime.now()));
            postService.insertPost(post);
            //生成的postId
           postId= post.getPostId();
            logger.info("生成博客id"+postId);
            if(postId==null){
                logger.error("生成博客id失败");
                return ReturnResultUtil.failure("生成博客id失败");
            }

            String coverOption=newDraft.getCoverOption();
            String content=newDraft.getContent();
            //保证一些需要的文件
            Set<String> filesToKeep = new HashSet<>();
            //根据博客内容复制相关文件 将草稿id的文件搬到新的postId
            List<String> storageFileNames = RegularUtil.extractStorageFileNames(content);
            String targetDirStr = FileUtil.createDirPath(FileUtil.POST_IMG_DIR_NAME + File.separator + postId);

           // Map<String ,> reserve
            for (String fileName : storageFileNames) {
                //正则表达式
                List<String> parts = RegularUtil.splitFileName(fileName);
                String frontPart = parts.get(0);  // 资源id
                String backPart = parts.get(1);//文件名
                String fileExtension = "";//获取扩展名
                if (backPart != null && backPart.lastIndexOf(".") > 0) {
                    fileExtension = backPart.substring(backPart.lastIndexOf(".") + 1).toLowerCase();
                }
                if (frontPart.equals(String.valueOf(draftId))) {//判断草稿id
                    //移动图片
                    String sourcePathStr = FileUtil.createDirPath(FileUtil.TEMP_POST_IMG_DIR_NAME + File.separator + frontPart + File.separator + backPart);
                    Path sourcePath = Paths.get(sourcePathStr);  // 源文件路径
                    Path targetDir = Paths.get(targetDirStr);  // 目标目录路径
                    File maxFile = FileUtil.getMaxValueFileInDirectory(targetDirStr);
                    // System.out.println(file.getName());
                    String newFileName = "1";
                    if (maxFile != null) {
                        newFileName = String.valueOf(Integer.parseInt(Objects.requireNonNull(FileUtil.extractNumber(maxFile.getName()))) + 1);
                    }
                    newFileName = newFileName + "." + fileExtension;
                    boolean isCopy = FileUtil.copyFileAndRename(sourcePath, targetDir, newFileName);
                    if (isCopy) {
                        //修改content
                        content=FileUtil.replaceStorageFileName(content, fileName, postId + "_" + newFileName);
                        filesToKeep.add(newFileName);
                    }
                }
            }
            logger.info("更改内容"+content);
            //博客封面
            if( "single".equals(coverOption)){
                //移动封面
                String dir=FileUtil.createDirPath(FileUtil.TEMP_POST_COVER_DIR_NAME);
                File dirFile=new File(dir);
                //找到文件
                List<File> fileList=FileUtil.findFilesByNameWithoutExtension(dirFile,draftId);
                File firstMatchingFile = null;
                if (!fileList.isEmpty()) {
                    // 遍历文件列表，获取第一个符合条件的文件路径
                    for (File file : fileList) {
                        if (file.getName().startsWith(draftId)) {
                            firstMatchingFile= file;
                            break;  // 找到第一个符合条件的文件，停止遍历
                        }
                    }
                }
                //开始复制
                if(firstMatchingFile!=null) {
                    Path sourcePath = Paths.get(firstMatchingFile.getAbsolutePath());  // 源文件路径
                    Path targetDir = Paths.get(FileUtil.createDirPath(FileUtil.POST_COVER_DIR_NAME));  // 目标目录路径
                    boolean isOk=FileUtil.copyFileAndRename(sourcePath, targetDir,postId+"."+FileUtil.getImageType(firstMatchingFile));
                    if(isOk){
                        logger.info("移动封面成功");
                    }
                }
            }
            //更改标签
            postService.updatePostTags(postId,newDraft.getTags());
            logger.info("更改标签成功");
            //修改博客内容
            postService.updatePostContent(postId,content);
            //向博客页面插入数据
            BlogPostDetails blogPostDetails=new BlogPostDetails();
            blogPostDetails.setPostId(postId);
            blogPostDetails.setBlogType(newDraft.getArticleType());
            blogPostDetails.setOriginalUrl(newDraft.getOriginalUrl());
            blogPostDetails.setBlogDescribe(newDraft.getDescription());
            postService.insertBlogPostDetails(blogPostDetails);
            //删除不需要的文件夹和文件
            cleanUpFiles(targetDirStr,filesToKeep);
            FileUtil.deleteDirectory(new File(FileUtil.createDirPath(FileUtil.TEMP_POST_IMG_DIR_NAME+File.separator+draftId)));
            logger.info("删除整个临时文件夹"+draftId);
            String dir = FileUtil.resourcePath + File.separator + FileUtil.TEMP_POST_COVER_DIR_NAME;
            FileUtil.deleteFilesByPartialName(dir, draftId);
            logger.info("删除临时文件： "+dir+", 前缀名: "+draftId);

            //更新热门
            updateHotTopics(postId);
        }catch (Exception e) {
            logger.error("发布出错"+e);
            //执行文件删除功能
            try {
                FileUtil.deleteDirectory(new File(FileUtil.createDirPath(FileUtil.POST_IMG_DIR_NAME+File.separator+postId)));
                String dir = FileUtil.resourcePath + File.separator + FileUtil.POST_COVER_DIR_NAME;
                FileUtil.deleteFilesByPartialName(dir, String.valueOf(postId));
            }catch (Exception e1){
                logger.error("发布失败 并存在文件未删除"+e1);
            }
            return ReturnResultUtil.failure("发布失败");
        }
        return ReturnResultUtil.success("发布成功");
    }
    public void updateHotTopics(long postId){
        String HOTSPOT_LIST_KEY= RedisKeyPrefixConfig.BLOG_LIST_HOTSPOT_KEY;
        // Lua 脚本：将元素推入列表，并确保列表不超过最大长度
        String luaScript =
                "redis.call('lpush', KEYS[1], ARGV[1]);" +  // 将元素推入列表头部
                        "redis.call('ltrim', KEYS[1], 0, tonumber(ARGV[2]) - 1);";  // 确保列表大小不超过最大长度
        // 执行脚本，传递参数
        List<String> keys = Collections.singletonList(HOTSPOT_LIST_KEY);
        int size= RedisKeyPrefixConfig.BLOG_MAX_HOTSPOT_SIZE;
        List<String> args = Arrays.asList(String.valueOf(postId), String.valueOf(size));
        // 执行 Lua 脚本
        redisTemplate.execute(new DefaultRedisScript<>(luaScript, String.class), keys, args.toArray());
    }
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
    private static void cleanUpFiles(String dirPath, Set<String> filesToKeep){
        // 获取需要删除的文件
        List<File> filesToDelete = FileUtil.getFilesToDelete(dirPath,filesToKeep);
        // 使用 Lambda 表达式提交删除任务
        for (File file : filesToDelete) {
            executorService.submit(() -> {
                // Lambda 表达式实现的删除任务
                try {
                    if (file.exists()) {
                        boolean deleted = file.delete();
                        if (deleted) {
                            logger.info("线程池删除的文件是: " + file.getName());
                        } else {
                            logger.error("线程池删除文件失败" + file.getName());
                        }
                    } else {
                        System.out.println("线程池没有找到文件: " + file.getName());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

        // 关闭线程池
        executorService.shutdown();

        // 等待所有任务完成
        try {
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
        }
    }
}

